/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-基础组件封装层-SpringBoot组件封装-核心依赖
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.boot.web.response.status;

// import com.fasterxml.jackson.annotation.JsonFormat;

import cn.hutool.json.JSONObject;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.taipingframework.boot.web.support.ApiHelper;
import com.taipingframework.utility.exception.UtilityException;
import com.taipingframework.utility.web.IApiStatus;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.TreeMap;

/**
 * api 返回对象状态的定义
 */
// @JsonFormat(shape = JsonFormat.Shape.OBJECT) // 序列化枚举类型，所有字段都会出现在JSON字符串中，JSON字符串表示的是一个JSON对象
public enum ExceptionStatusEnum implements IApiStatus {
    UNSUPPORTED_BUT_HTTP("FW0900", "No thread-bound request found: Are you referring to request attributes outside of an actual web request, "
            + "or processing a request outside of the originally receiving thread? "
            + "If you are actually operating within a web request and still receive this message, "
            + "your code is probably running outside of DispatcherServlet: In this case, "
            + "use RequestContextListener or RequestContextFilter to expose the current request."),
    WITHOUT_TOKEN_IN_HTTP_HEADER("FW0901", "HTTP请求头未携带会话标识`TOKEN`"),
    EXPIRED_TOKEN_IN_HTTP_HEADER("FW0902", "HTTP请求头携带的会话标识`TOKEN`已过期"),
    INVALID_TOKEN_IN_HTTP_HEADER("FW0903", "HTTP请求头携带的会话标识`TOKEN`参数格式不匹配"),
    UNABLE_GET_CONFIG_PROJECT("FW0904", "无法获取项目名称的唯一标识"),
    UNABLE_GET_CONFIG_MODULE("FW0905", "无法获取项目模块的唯一标识"),
    UNABLE_GET_CONFIG_RUN_ENV("FW0906", "无法获取项目运行环境的唯一标识"),
    UNABLE_GET_CLIENT_IDENTITY("FW0907", "无法获取本地会话的唯一标识"),
    UNABLE_GET_CACHE_HANDLER("FW0908", "无法获取标准缓存(读/写)处理器"),
    UNABLE_GET_OBJECT_MAPPER("FW0909", "无法获取(读/写)JSON字符串的ObjectMapper对象"),
    TOKEN_DATA_REQUIRED_NON_NULL("FW0910", "`TOKEN`中的数据不允许设置为空"),
    ILLEGAL_PROPERTIES_ALGORITHM("FW0911", "签名算法要求必须显式指定"),
    ILLEGAL_PROPERTIES_ASYMMETRIC("FW0912", "非对称签名算法要求公钥`PRIVATE-KEY`或私钥`PUBLIC-KEY`不允许为空"),
    ILLEGAL_PROPERTIES_SYMMETRICAL("FW0913", "对称签名算法要求秘钥`SECRET-KEY`不允许为空"),
    ILLEGAL_PROPERTIES_PLAINTEXT("FW0914", "未指定签名算法要求密码字符串`PLAIN-KEY`不允许为空"),
    UNSUPPORTED_ALGORITHM_ASYMMETRIC("FW0915", "使用的签名算法不支持生成非对称公钥/私钥"),
    UNSUPPORTED_ALGORITHM_SYMMETRICAL("FW0916", "使用的签名算法不支持生成对称秘钥"),
    NEBULOUS_SECRET_KEY_TYPE("FW0917", "未明确指定使用何种秘钥类型创建、验证、获取`TOKEN`"),
    INCORRECT_TOKEN_FROM_CLIENT("FW0918", "在会话有效期内使用了无效的身份凭证访问系统"),
    OVERFLOW_SESSION_LIMIT_SIZE("FW0919", "当前账号已超出可登录的设备数量上限"),
    OVERFLOW_CLIENT_LIMIT_SIZE("FW0920", "当前终端已有账号登录系统，若要切换系统的登录账号，请先退出已登录的账号"),
    ILLEGAL_MYSELF_PROFILE_TOKEN("FW0921", "无法使用其它终端的身份凭证访问系统"),
    ILLEGAL_OTHERS_PROFILE_TOKEN("FW0922", "无法使用未经许可的身份凭证访问系统"),
    INCORRECT_DEVICE_FROM_CLIENT("FW0923", "无法使用其它设备的身份凭证访问系统"),
    UNABLE_GET_MANAGED_PROFILE("FW0924", "无法获取远程客户端MANAGED_PROFILE配置信息");

    ExceptionStatusEnum(String code, String message) {
        this.code = code;
        this.message = message;
    }

    private String code;
    private String message;

    @JsonValue // 这个注解标注在某个getter方法上，表示该方法是当前枚举的实际表示，只有当前字段的常量值会出现在JSON字符串中
    @Override
    public String getCode() {
        return this.code;
    }

    @Override
    public String getMessage() {
        return this.message;
    }

    @Override
    public String toJSON() throws UtilityException {
        return ApiHelper.toJSON(this);
    }

    /**
     * Jackson反序列化
     */
    @JsonCreator
    public static ExceptionStatusEnum fromCode(String code) throws IllegalArgumentException {
        if (keyValuePairs.size() <= 0) {
            TreeMap<String, String> treeMap = Stream.of(ExceptionStatusEnum.values())
                    .collect(Collectors.toMap(
                            ExceptionStatusEnum::getCode,
                            ExceptionStatusEnum::name,
                            (oldValue, newValue) -> newValue,
                            TreeMap::new));
            keyValuePairs.putAll(treeMap);
        }
        if (!keyValuePairs.containsKey(code)) {
            throw new IllegalArgumentException(String.valueOf(code));
        }
        return ExceptionStatusEnum.valueOf(keyValuePairs.get(code));
    }

    /**
     * 唯一标识字段 与 enum-name的映射关系
     */
    private static TreeMap<String, String> keyValuePairs = new TreeMap<>();

    /**
     * hutool反序列化
     * 根据特定字段获取 具体的 枚举实例，其实，code也可以是不同枚举字段的组合，也可以是一个对象，只要求它们的组合是唯一的，能够映射唯一的一个枚举实例即可。
     */
    public static ExceptionStatusEnum get(JSONObject jsonObj) throws IllegalArgumentException {
        String code = String.valueOf(jsonObj.get(ApiHelper.OBJECT_IDENTITY_KEY));
        return fromCode(code);
    }

}
